package com.cy.game

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.helloandroid.AppUtil
import com.helloandroid.app.model.AppCache
import com.helloandroid.ext.parseCyInfo
import com.helloandroid.ext.process
import com.helloandroid.tools.Http.asyncHttpReq
import com.helloandroid.tools.MyLog
import com.helloandroid.tools.NetWorkUtil
import kotlinx.coroutines.*
import org.json.JSONArray
import org.json.JSONObject
import java.io.BufferedReader
import java.io.InputStreamReader
import java.lang.StringBuilder
import java.nio.charset.StandardCharsets

class CyViewModel : ViewModel() {

    var tick = false

    private fun asyncLoadLevel(): String {
        val bufferedReader = BufferedReader(InputStreamReader(AppUtil.app.assets.open("levellll.json"), StandardCharsets.UTF_8))
        val sb = StringBuilder()
        var line = bufferedReader.readLine()
        while (line != null) {
            sb.append(line)
            line = bufferedReader.readLine()
        }
        bufferedReader.close()
        return sb.toString()
    }

    private fun asyncLoadExplain(): String {
        val bufferedReader = BufferedReader(InputStreamReader(AppUtil.app.assets.open("ChengYu.json"), StandardCharsets.UTF_8))
        val sb = StringBuilder()
        var line = bufferedReader.readLine()
        while (line != null) {
            sb.append(line)
            line = bufferedReader.readLine()
        }
        bufferedReader.close()
        return sb.toString()
    }

    fun getInfo(callback: (Boolean, CyInfo?) -> Unit){
        viewModelScope.launch {
            // 第1个任务. 先缓存关卡
            if (AppCache.allLevelJsonArr == null){
                val levelInfoDefer = async(Dispatchers.Default) {
                    asyncLoadLevel()
                }
                val levelStr = levelInfoDefer.await()
                AppCache.allLevelJsonArr = JSONArray(levelStr)
                MyLog.info("total level:${AppCache.allLevelJsonArr!!.length()}")
            }

            if (AppCache.allExplainJsonObj == null){
                val explainInfoDefer = async(Dispatchers.Default){
                    asyncLoadExplain()
                }
                val explainStr = explainInfoDefer.await()
                AppCache.allExplainJsonObj = JSONObject(explainStr)
            }

            // 第2个任务(非并行)
            val info = AppCache.copyCyInfo()
            if (info != null){
                callback(true,info)
            }else{
                if (!NetWorkUtil.networkConnected()){
                    AppUtil.toast("请打开网络!")
                    callback(false,null)
                }else{
                    val url = "game/chengyu/info?user_id=${AppUtil.user.user_id}"
                    val jsonObj = JSONObject(asyncHttpReq(url))
                    val parseResult = jsonObj.process(JSONObject::parseCyInfo)
                    val cyInfo = parseResult.obj as CyInfo
                    if(parseResult.err == 0){
                        AppCache.cyInfo = cyInfo
                        callback(true,AppCache.copyCyInfo())
                    }else{
                        MyLog.elog("err:${parseResult.err},msg:${parseResult.msg}")
                        callback(false,null)
                    }
                }
            }
        }
    }

    fun startPerSecondTick(action:()->Unit){
        viewModelScope.launch {
            launch(Dispatchers.Default){
                while (isActive){
                    delay(1000)
                    withContext(Dispatchers.Main){
                        action()
                    }
                }
            }
        }
    }

    fun delayRun(dt:Float,action:()->Unit){
        viewModelScope.launch {
            delay((dt * 1000).toLong())
            action.invoke()
        }
    }

    fun loadLevel(level:Int,action:(JSONArray)->Unit){
        action(AppCache.allLevelJsonArr!!.getJSONArray(level - 1))
    }

    fun startTick(action: () -> Unit){
        if (tick){
            return
        }
        tick = true
        viewModelScope.launch {
            while (isActive && tick){
                delay(1000L)
                action.invoke()
            }
        }
    }

    fun stopTick(){
        tick = false
    }
}